#ifndef DHD_FRONT_CLIENT
#define DHD_FRONT_CLIENT

#include <string>
#include <map>

#include <boost/asio.hpp>
#include <boost/thread.hpp>

#include "c_config.h"
#include "c_interaction.h"
#include "c_server_thread.h"

using boost::asio::ip::tcp;


namespace dhd
{
namespace client
{

class ServerThread;
class Interaction;
class Client;
   
   
extern Client * g_client;

// wraps g_frontend.handle_fuse_request
void handle_fuse_request( const char * path, PInteraction & inter );


class Client
{   
   boost::mutex   client_mutex;

   std::string    config_file;
   
   ClientConfig   *config;
   
   //-----------------------------
   // Server Management
   //-----------------------------
   
   // Maps "hostname:portnum" as specified in the config file to the ServerThread
   typedef std::map< std::string, PServerThread > ServerMap;
   
   ServerMap  server_map;
   
   
   //-----------------------------
   // Unioned Root Directory
   //-----------------------------
   struct UnionEntry
   {
       std::string        name;
       int                mode;
       int                inode;
       ServerThread      *server;
   };

   typedef std::map< std::string, UnionEntry >  UnionMap;
   
   UnionMap  union_map;
   int       start_sec;  // Startup time for the daemon will be the mtime/ctime for the union
   int       start_nsec; // directory.
   
   
 public:
   
   // throws ConfigurationError on failure
   Client( const std::string & _config_file );
   
   ~Client();

   
   void reread_config_file() {} // TODO
   
   void handle_fuse_request( const char * path, PInteraction & inter );
   
   //---------------------------------------------------------
   // Union Methods
   //
   ServerThread * get_server_for( const char * path );
   
   // This method may be called to overwrite an existing entry when the mode
   // of the directory changes
   void add_dir( const std::string & name, 
                 int                 mode, 
                 int                 inode, 
                 ServerThread      * server );
   
   void del_dir( const std::string & name );
   
   void del_all( ServerThread * server );
   
   
 private:
   
   // /dhd_fs_status helper
   void handle_status_request( PInteraction & inter );
   
   std::string get_status();
   
   //-----------------------------
   // Union Helper Functions
   //-----------------------------
   void handle_union_request( PInteraction & inter );
   
   int union_ignore  ( PInteraction & inter );
   int union_readdir ( PInteraction & inter );
   int union_getattr ( PInteraction & inter );
   int union_access  ( PInteraction & inter );
   int union_chmod   ( PInteraction & inter );
   int union_chown   ( PInteraction & inter );
   int union_statfs  ( PInteraction & inter );
   int union_fsync   ( PInteraction & inter );
   int union_mknod   ( PInteraction & inter );
   
   
   int union_getxattr    ( PInteraction & inter );
   int union_setxattr    ( PInteraction & inter );
   int union_listxattr   ( PInteraction & inter );
   int union_removexattr ( PInteraction & inter );
};




} // end namespace dhd::client
} // end namespace dhd



#endif